
package com.db4o.internal.odbgen.fileutils;

import java.io.*;
/**
 * Passes recursively through the directory structure and for each directory entry,
 * calls the process() callback function. This function is abstract and must be implemented
 * by each subclass of DirCounter
 * @author liviug
 */
public abstract class DirIterator 
{
    /**
     * If this is true, then iterateDir() will enter any subdirectories of the
     * current directory, else subdirectories will not be iterated. By default
     * it is true.
     */
    protected boolean enterSubdirectories=true;

    /**
     * Starts iterating recursively through directory structure begining with 'f'.
     * For each file and directory found, calls process().
     * <br>If this.enterSubdirectories==false then only files and directories of the
     * current directory will be send to process()
     * <br>Note: This version iterates first through all directories then
     * iterates through all files in the current directory
     * @param f Current directory to be iterated.
     * @throws java.io.IOException This exception is throwed if 'path' doesn't exist
     * or is not a directory. If process() throws this exception, then start() retrows it
     * This must be a path to a directory entry, not to a file.
     */
    protected final void iterateDir(File f) throws IOException 
    {
        int i;
        File currentFile;
        String[] list=f.list();
        String absolutePath=f.getAbsolutePath()+File.separator;
        String absoluteFile;
        //iterate through all files and directories
        for( i=0; i<list.length; i++ )
        {
            absoluteFile=absolutePath+list[i];
            currentFile=new File(absoluteFile);
            if( currentFile.isDirectory() )
            {
                process(currentFile);
                if( enterSubdirectories )
                    iterateDir(currentFile);
            }
            else
                process(currentFile);
        }
        return;
    }
    /**
     * For each file or directory encountered by start(), process() must implement
     * the code to handle it.
     * <br>This is an abstract member so it must be implemented by each subclass
     * of DirIterator.
     * @param f The current file or directory which is being processed.
     * @throws java.io.IOException In case if something happend with 'f',
     * process() may throw any kind of IOException. If this happens, the exception
     * is handled or retrowed by start.
     * @see liviu.utils.io.DirIterator#start
     */
    protected abstract void process(File f) throws IOException;
    /**
     * Sets the enterSubdirectories field.
     * @param enterSubdirectories If true, the iteration will include
     * any subdirecbories else, subdirectories will be ignored
     */
    protected void setEnterSubdirectories(boolean enterSubdirectories) 
    {
        this.enterSubdirectories=enterSubdirectories;
        return;
    }
    /**
     * Calls iterateDir() which actualy iterates recursively through
     * the directory structure starting with 'path'
     * @param path The root directory
     * @exception java.io.IOException This exception is retrowed if some exception occured
     * in iterateDir()
     */
    protected void start(String path) throws IOException 
    {
        File f=new File(path);
        //check if f exists or is a directory
        if( !f.exists() )
            throw new IOException(f.getName()+" does not exists");
        if( !f.isDirectory() )
            throw new IOException(f.getName()+" must be a directory");
        iterateDir(f);
        return;
    }
}